home *** CD-ROM | disk | FTP | other *** search
-
- /* If you don't define SystemSixOrLater, you will need to link against */
- /* the library version of SysEnvirons */
-
- #define SystemSixOrLater 1
-
- #include <Icons.h>
- #include <OSUtils.h>
- #include <Resources.h>
- #include <Memory.h>
-
- /*
- ShowIcon7.c
-
- ShowINIT compatible routine that shows 'ICN#' and 'iclx' flavor icons.
- For use by all INITs in System 7 and beyond.
-
- This code is based on Patrick C. Beard's ShowIconFamily
- by Patrick C. Beard, which in turn was derived from the
- original ShowInit by Paul Mercer, Darin Adler,
- Paul Snively, and Steve Capps.
-
- Modified by James W. Walker for compatibility with IconWrap 1.2,
- for use as a separate code resource, and to use the new System 7
- icon-drawing routines. This code is in the public domain.
-
- Dec 17, 1994 - Modified to work with MPW and universal headers.
- IconFamilies.h is now offically called 'Icons.h'. QDGlobals
- is now an official type. Removed inline assembly to rotate a
- word left. -- Charlie Reiman
-
- Addresses for James W. Walker: 76367,2271@compuserve.com or
- walkerj@math.scarolina.edu
-
- Instructions for use:
-
- • Create a family of icons with ResEdit 2.1 or later. This will
- include 'ICN#', 'icl4', & 'icl8' icons, all with the
- same resource ID.
-
- To use within a larger INIT project:
- • #define SEPARATE_CODE 0 below.
- • Call ShowIcon7( id, adv ) with the resource id of
- the family that you used. The Boolean parameter adv
- indicates whether you want the next use of ShowIcon7
- to advance to a new position. Normally you pass TRUE,
- but you can get an animated-icon effect by passing FALSE
- all except the last time you call ShowIcon7.
-
- To use as a separate code resource:
- • #define SEPARATE_CODE 1 below.
- • Set the project type to code resource, set the code type
- and resource ID (I use type 'Code', ID -4048 for cdevs),
- compile and merge into your INIT or cdev file.
- Set the resource type to Locked, so you won't have
- to call HLock when you use it.
- • In your main INIT code, call ShowIcon7 like so:
- pascal void (*ShowIcon7)( short resid, Boolean adv );
- Handle show_init;
-
- show_init = GetResource( 'Code', -4048 );
- ShowIcon7 = (pascal void (*)(short, Boolean))
- StripAddress( *show_init );
- ShowIcon7( iconID, advance );
- */
-
- #define SEPARATE_CODE 0
-
-
- #if SEPARATE_CODE
- #define ShowIcon7 main /* JWW */
- #endif
-
- #ifndef nil
- #define nil ((void*)0L)
- #endif
-
- #ifndef topLeft
- #define topLeft(r) ((Point*)&r)[0])
- #endif
- #ifndef botRight
- #define botRight(r) ((Point*)&r)[1])
- #endif
-
- typedef struct myQDGlobals {
- QDGlobals theGlobals;
- long end; /* a5 points here */
- } myQDGlobals; /* CJR */
-
- /* prototypes */
- pascal void ShowIcon7(short iconId, Boolean advance);
- static void DrawBWIcon( short iconId, Rect *icon_rect, Boolean visible );
- static void Next_position( void );
- static void GetIconRect( register Rect* iconRect, Rect *screen_rect );
-
- /* this is where it all happens. */
-
- pascal void ShowIcon7( short iconId, Boolean advance )
- {
- long oldA5;
- myQDGlobals qd; /* our QD globals. */
- SysEnvRec environment; /* machine configuration. */
- CGrafPort gp; /* our grafport. */
- Rect icon_rect;
- OSErr err;
-
- /* get a value for A5, a structure that mirrors qd globals. */
- oldA5 = SetA5((long)&qd.end);
- InitGraf(&qd.theGlobals.thePort);
-
- /* find out what kind of machine this is. */
- SysEnvirons(curSysEnvVers, &environment);
-
- GetIconRect( &icon_rect, &qd.theGlobals.screenBits.bounds );
-
- /*
- The old IconWrap INIT patches CopyBits but does not know about
- CopyMask or IconDispatch. So in the color case, we draw the
- black and white icon with an empty mask region.
- */
-
- if ( (environment.systemVersion >= 0x0700) && environment.hasColorQD )
- {
- OpenCPort(&gp);
- DrawBWIcon( iconId, &icon_rect, false );
- err = PlotIconID( &icon_rect, atNone, ttNone, iconId );
- CloseCPort(&gp);
- }
- else
- {
- OpenPort((GrafPtr)&gp);
- DrawBWIcon( iconId, &icon_rect, true );
- ClosePort((GrafPtr)&gp);
- }
-
- if (advance)
- Next_position(); /* JWW */
-
- SetA5(oldA5);
- }
-
- /*
- ShowInit's information is nestled at the tail end of CurApName.
- It consists of a short which encodes the next horizontal offset,
- and another short which is that value checksummed with the function below.
- */
-
- #define CurApName_LM 0x910
- #define ShowINITTable ((short*)(CurApName_LM + 32 - 4))
- #define CheckSumConst 0x1021 /* magic value to check-sum with. */
-
- #define InitialXPosition 8 /* initial horizontal offset. */
- #define YOffset 40 /* constant from bottom to place the icon. */
- #define XOffset 40 /* amount to change it by. */
- #define ICON_WIDTH 32
- #define kDefaultRes 0x00480000 /* Default resolution is 72 DPI; Fixed type */
-
- /* CheckSum() computes the magic value to determine if ShowInit's have run already. */
-
- static short CheckSum(short x)
- {
- register unsigned short y = x;
- y = ( y >> 15 ) + (y << 1); /* CJR -- was asm { rol.w #1, x } */
- return (y ^ CheckSumConst);
- }
-
- /*
- GetIconRect() generates an appropriate rectangle to display the
- next INIT's icon in.
- It is also responsible for updating the horizontal
- position in low memory. This is a departure from
- the original ShowInit code, which updates low
- memory AFTER displaying the icon. -- changed by JWW
- This code won't generate an icon position until it is certain that the icon can be loaded, so the
- same behaviour occurs.
-
- This routine also generates a rectangle which is guaranteed to be onscreen. It
- does this by taking the horizontal offset modulo the screen width to generate
- the horizontal position of the icon, and the offset divided by the screen
- width to generate the proper row.
- */
-
- static void GetIconRect(register Rect* iconRect, Rect *screen_rect )
- {
- register short screenWidth;
-
- screenWidth = screen_rect->right - screen_rect->left;
- screenWidth -= screenWidth % XOffset;
- /* if we are the first INIT to run we need to initialize the horizontal value. */
- if (CheckSum(ShowINITTable[0]) != ShowINITTable[1])
- ShowINITTable[0] = InitialXPosition;
-
- /* compute top left of icon's rect. */
- iconRect->left = (ShowINITTable[0] % screenWidth);
- iconRect->top = screen_rect->bottom -
- YOffset * (1 + (ShowINITTable[0] / screenWidth));
- iconRect->right = iconRect->left + 32;
- iconRect->bottom = iconRect->top + 32;
-
- }
-
- /*
- JWW: In Beard's original version, this was done at the end of
- GetIconRect. That caused incorrect behavior when IconWrap 1.2 was
- used to wrap icons. Namely, if an INIT using that version of
- ShowIconFamily was the first in a row, then the second icon in that
- row would land on top of it.
- */
- static void Next_position( void )
- {
- /* advance the position for the next icon. */
- ShowINITTable[0] += XOffset;
-
- /* recompute the checksum. */
- ShowINITTable[1] = CheckSum(ShowINITTable[0]);
- }
-
- /* DrawBWIcon() draws the 'ICN#' member of the icon family. */
-
- void DrawBWIcon( short iconId, Rect *icon_rect, Boolean visible )
- {
- Handle icon;
- BitMap source, destination;
- RgnHandle empty_mask;
- GrafPtr port;
-
- icon = (Handle)Get1Resource('ICN#', iconId);
- if (!icon)
- return;
- HLock(icon);
-
- /* prepare the source and destination bitmaps. */
- source.baseAddr = *icon + 128; /* mask address. */
- source.rowBytes = 4;
- SetRect(&source.bounds, 0, 0, 32, 32);
- GetPort( &port );
- destination = ((GrafPtr)port)->portBits;
- empty_mask = visible? nil : NewRgn();
-
- /* transfer the mask. */
- CopyBits(&source, &destination, &source.bounds, icon_rect,
- srcBic, empty_mask);
-
- /* and the icon. */
- source.baseAddr = *icon;
- CopyBits(&source, &destination, &source.bounds, icon_rect,
- srcOr, empty_mask);
-
- if (empty_mask) DisposeRgn( empty_mask );
- }
-